"use client"; // 必须添加：Context是客户端特性

import { createContext, useContext, useEffect, useState, ReactNode } from "react";
import { ethers, BrowserProvider } from "ethers";

// 定义Context类型
interface WalletContextType {
  address: string | null; // 钱包地址（0x开头）
  balance: string | null; // ETH余额
  connectWallet: () => Promise<void>; // 连接钱包
  disconnectWallet: () => void; // 断开钱包
  isLoading: boolean; // 加载状态
  error: string | null; // 错误信息
  provider: BrowserProvider | null; // ethers提供者
}

// 创建Context（默认undefined）
const WalletContext = createContext<WalletContextType | undefined>(undefined);

// Provider组件（全局包裹）
export function WalletProvider({ children }: { children: ReactNode }) {
  const [address, setAddress] = useState<string | null>(null);
  const [balance, setBalance] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const [provider, setProvider] = useState<BrowserProvider | null>(null);

  // 1. 初始化：检查已有钱包连接
  useEffect(() => {
    const checkExistingConnection = async () => {
      if (!window.ethereum) return; // 无钱包环境，不处理

      try {
        // 请求已授权的账户
        const accounts = await window.ethereum.request({ method: "eth_accounts" });
        if (accounts.length > 0) {
          await setupWallet(accounts[0]); // 初始化钱包信息
        }

        // 监听账户变更（如用户切换钱包账户）
        const handleAccountsChanged = (newAccounts: string[]) => {
          if (newAccounts.length > 0) {
            setupWallet(newAccounts[0]);
          } else {
            resetWallet(); // 无账户，重置状态
          }
        };

        // 监听链变更（如用户切换ETH主网/测试网）
        const handleChainChanged = () => {
          window.location.reload(); // 链变更后刷新，避免数据不一致
        };

        // 绑定监听
        window.ethereum.on("accountsChanged", handleAccountsChanged);
        window.ethereum.on("chainChanged", handleChainChanged);

        // 清理监听（组件卸载时）
        return () => {
          window.ethereum.removeListener("accountsChanged", handleAccountsChanged);
          window.ethereum.removeListener("chainChanged", handleChainChanged);
        };
      } catch (err) {
        setError("Failed to check wallet connection");
        console.error("Check connection error:", err);
      }
    };

    checkExistingConnection();
  }, []);

  // 辅助函数：设置钱包信息（地址+余额）
  const setupWallet = async (account: string) => {
    try {
      const ethProvider = new BrowserProvider(window.ethereum!);
      setProvider(ethProvider);
      setAddress(account);

      // 查询ETH余额（格式化为ether单位，而非wei）
      const balance = await ethProvider.getBalance(account);
      setBalance(ethers.formatEther(balance));
      setError(null);
    } catch (err) {
      setError("Failed to load wallet data");
      console.error("Setup wallet error:", err);
    }
  };

  // 辅助函数：重置钱包状态
  const resetWallet = () => {
    setAddress(null);
    setBalance(null);
    setProvider(null);
    setError(null);
  };

  // 核心方法：连接钱包（请求用户授权）
  const connectWallet = async () => {
    setIsLoading(true);
    setError(null);

    try {
      // 1. 检查钱包是否安装
      if (!window.ethereum) {
        setError("Please install MetaMask first");
        return;
      }

      // 2. 请求用户授权账户
      const accounts = await window.ethereum.request({
        method: "eth_requestAccounts",
      });

      // 3. 授权成功，设置钱包信息
      if (accounts.length > 0) {
        await setupWallet(accounts[0]);
      }
    } catch (err) {
      // 处理用户拒绝授权的情况
      if ((err as Error).message.includes("User rejected")) {
        setError("You rejected the wallet connection");
      } else {
        setError("Failed to connect wallet");
      }
      console.error("Connect wallet error:", err);
    } finally {
      setIsLoading(false); // 无论成功失败，结束加载
    }
  };

  // 核心方法：断开钱包（前端状态重置，无需钱包授权）
  const disconnectWallet = () => {
    resetWallet();
  };

  // 提供Context值
  const contextValue: WalletContextType = {
    address,
    balance,
    connectWallet,
    disconnectWallet,
    isLoading,
    error,
    provider,
  };

  return (
    <WalletContext.Provider value={contextValue}>
      {children}
    </WalletContext.Provider>
  );
}

// 自定义Hook：简化Context使用（避免重复useContext+判断）
export function useWallet() {
  const context = useContext(WalletContext);
  if (!context) {
    throw new Error("useWallet must be used within a WalletProvider");
  }
  return context;
}
